package org.hilo.boot.app.config;

import java.util.Arrays;
import java.util.List;

import org.hilo.boot.app.web.AppWebListener;
import org.hilo.boot.core.UT;
import org.hilo.boot.core.web.HighestOrderWebFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
 * Base Spring WebMvcConfig
 * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
 * 
 * @author zollty
 * @since 2018-2-23
 */
abstract public class BaseWebMvcConfig implements WebMvcConfigurer {
    
    @Value("${hilo.web.trace-request:}")
    private String traceAll;
    
    @Autowired(required = false)
    @Qualifier("defaultControllerInterceptor")
    private HandlerInterceptorAdapter controllerInterceptor;
    
    @Bean
    @ConditionalOnProperty(prefix = "hilo.web.filter", name = "default", matchIfMissing = true)
    public HighestOrderWebFilter hiloWebFilter() {
        HighestOrderWebFilter filter = new HighestOrderWebFilter();
        if (traceAll.equals("all")) {
            filter.setTraceRequest(true);
        }
        return filter;
    }
    
    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter ret = new MappingJackson2HttpMessageConverter();
        ret.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.TEXT_HTML));
        ret.setObjectMapper(UT.Json.getObjectMapper());
        return ret;
    }
    
    @Bean
    public ServletListenerRegistrationBean<AppWebListener> myServletListener() {
        ServletListenerRegistrationBean<AppWebListener> appListener = 
                new ServletListenerRegistrationBean<AppWebListener>();
        appListener.setListener(new AppWebListener());
        return appListener;
    }
    
    @Override
    final public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(mappingJackson2HttpMessageConverter());
        
        moreMessageConverters(converters);
    }
    
    protected void moreMessageConverters(List<HttpMessageConverter<?>> converters) {}
    
    @Override
    final public void addInterceptors(InterceptorRegistry registry) {
        if (controllerInterceptor != null) {
            registry.addInterceptor(controllerInterceptor);
        }
        moreInterceptors(registry);
    }
    
    protected void moreInterceptors(InterceptorRegistry registry) {}
    
    @Override
    public final void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        
        moreArgumentResolvers(argumentResolvers);
    }
    
    protected void moreArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {}
    
    /**
     * 默认配置如下:<pre>
     * 
     * # Path of the Spring main dispatcher servlet.
     * server.servlet-path=/
     * 
     * # Path of the error controller.
     * server.error.path=/error
     * 
     * # Path pattern used for static resources.  
     * spring.mvc.static-path-pattern=/**
     * 
     * # Locations of static resources.  
     * spring.resources.static-locations=
     *     classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ 
     * 
     * </pre>
     * 
     * 参见： ResourceProperties
     */
    @Override
    public final void addResourceHandlers(ResourceHandlerRegistry registry) {
        moreResourceHandlers(registry);
    }
    
    protected void moreResourceHandlers(ResourceHandlerRegistry registry) {};


}
